class MyPromise {
    constructor(executor) {
        this.state = 'pending'//状态变量
        this.onFulfilledCallbacks = []
        this.onRejectedCallbacks = []
        const resolve = (value) => {//resolve接收到的参数，给then中函数使用
            //用户调用resolve时便把state状态修改，防止后续的reject再执行
            if (this.state === 'pending') {
                this.state = 'fulfilled'
                //把then中存起来的函数拿出来执行
                this.onFulfilledCallbacks.forEach(fn => fn(value))
            }
        }
        const reject = (reason) => {//reject接收到的参数，给catch中函数使用
            //用户调用reject时便把state状态修改，防止后续的resolve再执行
            if (this.state === 'pending') {
                this.state = 'rejected'
                //把catch中存起来的函数拿出来执行
                this.onRejectedCallbacks.forEach(fn => fn(reason))
            }
        }
        executor(resolve, reject)
    }
    then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value
        onRejected = typeof onRejected === 'function' ? onRejected : (reason) => { throw reason }
        //默认返回一个promise
        const newPromise = new MyPromise((resolve, reject) => {
            //当promise内的代码是同步执行（没有异步代码），这会使得resolve也是同步执行，这时状态变量便会变成fulfilled，所以需要then自己执行内部的回调函数
            if (this.state === 'fulfilled') {//判断onFulfilled是否要自己触发
                setTimeout(() => {//为了保证then是异步的，但是我打造不出微任务，只能这样
                    try {
                        const result = onFulfilled()//执行then中第一个函数，并将返回值resolve，给下一个then使用
                        resolve(result)
                    } catch (err) {
                        reject(err)//如果报错了，后面的then就失效了
                    }
                }, 0)
            }
            //当promise内的代码是同步执行（没有异步代码），这会使得reject也是同步执行，这时状态变量便会变成rejected，所以需要then自己执行内部的回调函数
            if (this.state === 'rejected') {
                setTimeout(() => {//为了保证then是异步的，但是我打造不出微任务，只能这样
                    try {
                        const result = onRejected()//执行then中第二个函数，并将返回值resolve，给下一个then使用
                        resolve(result)
                    } catch (err) {
                        reject(err)//如果报错了，后面的then就失效了
                    }
                }, 0)
            }
            //当promise内的代码异步执行，这会使得resolve也是异步执行，所以状态为pending，这是便可以先将then内的回调函数先存起来
            if (this.state === 'pending') {//将onFulfilled、onFulfilled存起来
                this.onFulfilledCallbacks.push((value) => {
                    setTimeout(() => {//为了保证then是异步的，但是我打造不出微任务，只能这样
                        try {
                            const result = onFulfilled(value)//执行then中第一个函数，并将返回值resolve，给下一个then使用
                            resolve(result)
                        } catch (err) {
                            reject(err)//如果报错了，后面的then就失效了
                        }
                    }, 0)
                })
                this.onRejectedCallbacks.push((reason) => {
                    setTimeout(() => {//为了保证then是异步的，但是我打造不出微任务，只能这样
                        try {
                            const result = onRejected(reason)//执行then中第二个函数，并将返回值resolve，给下一个then使用
                            resolve(result)
                        } catch (err) {
                            reject(err)//如果报错了，后面的then就失效了
                        }
                    }, 0)
                })
            }
        })
        return newPromise
    }
    catch(onRejected){
        return this.then(undefined,onRejected)
    }
    finally(callback){
        return this.then((value)=>{//this指向调用finally的promise实例对象
            return MyPromise.resolve(callback()).then(()=>value)//将value返回，给下一个then使用，而不是返回finally内回调函数返回的值
        },(reason)=>{
            return MyPromise.resolve(callback()).then(()=>{
                throw reason//将reason抛出，给下一个catch使用
            })
        })
    }
    static race(promises) {
        return new MyPromise((resolve, reject) => {
            promises.forEach((promise) => {
                promise.then((value) => {
                    resolve(value)
                }, (reason) => {
                    reject(reason)
                })
            })
        })
    }
    static all(promises) {
        const results = []
        let count = 0
        return new MyPromise((resolve, reject) => {
            for(let i = 0; i < promises.length; i++){
                promises[i].then((value) => {
                    results[i] = value
                    count++
                    //不能直接拿results的长度来判断，因为如果最后一个先执行完，则results的长度会直接变的和promises的长度相等
                    if(count === promises.length){
                        resolve(results)
                    }
                }, (reason) => {
                    reject(reason)
                })
            }
        })
    }
    static any(promises) {
        const results = []
        let count = 0
        return new MyPromise((resolve, reject) => {
            for(let i = 0; i < promises.length; i++){
                promises[i].then((value) => {
                    resolve(value)
                }, (reason) => {
                    results[i] = reason
                    count++
                    //不能直接拿results的长度来判断，因为如果最后一个先执行完，则results的长度会直接变的和promises的长度相等
                    if(count === promises.length){
                        reject(new AggregateError(results,'All promises were rejected'))
                    }
                })
            }
        })
    }
    static resolve(value) {
        return new MyPromise((resolve, reject) => {
            resolve(value)
        })
    }
    static reject(reason) {
        return new MyPromise((resolve, reject) => {
            reject(reason)
        })
    }
    static allSettled(promises) {
        return new MyPromise((resolve, reject) => {
            const results = []
            let count = 0
            for(let i = 0; i < promises.length; i++){
                promises[i].then((value) => {
                    results[i] = {status: 'fulfilled',value}
                    count++
                    if(count === promises.length){
                        resolve(results)
                    }
                }, (reason) => {
                    results[i] = {status: 'rejected',reason}
                    count++
                    if(count === promises.length){
                        resolve(results)
                    }
                })
                //也可以这样写count++
                // .finally(()=>{
                //     count++
                //     if(count === promises.length){
                //         resolve(results)
                //     }
                // })
            }
        })
    }
}
// let p = new MyPromise((resolve, reject) => {
//     setTimeout(() => {
//         resolve('ok')
//     }, 1000)
// })
// p.then((res) => {
//     console.log(res)
//     return 'ok1'
// }).then((res)=>{
//     console.log(res)
// })

function A() {
    return new MyPromise((resolve, reject) => {
        setTimeout(() => {
            console.log('A');
            resolve('success A')
        }, 1000)
    })
}
function B() {
    return new MyPromise((resolve, reject) => {
        setTimeout(() => {
            console.log('B');
            reject('success B')
        }, 500)
    })
}
function C() {
    return new MyPromise((resolve, reject) => {
        setTimeout(() => {
            console.log('C');
            reject('success C')
        }, 100)
    })
}
// MyPromise.race([A(), B(), C()]).then((res) => {
//     console.log(res)
// }, (res) => {
//     console.log(res)
// })

// MyPromise.all([A(), B(), C()]).then((res) => {
//     console.log(res)
// }, (res) => {
//     console.log(res)
// })

// MyPromise.any([A(), B(), C()]).then((res) => {
//     console.log(res)
// }, (res) => {
//     console.log(res)
// })

MyPromise.allSettled([A(), B(), C()]).then((res) => {
    console.log(res)
}, (res) => {
    console.log(res)
})